﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json.Linq;

namespace Yqd.Core
{
    #region 上传文件类

    /// <summary>
    /// 文件上传类
    /// </summary>
    public class FileUpload
    {
        /// <summary>
        /// 上传生成的文件列表
        /// 0：为存入数据库的带sys的文件目录
        /// 1：生成的文件名
        /// 2：原始文件名
        /// </summary>
        public List<string[]> FileNames { get; set; }

        /// <summary>
        /// 上传出错信息
        /// </summary>
        public string ErrMsg { get; set; }

        private string[] _allowSuffix;

        /// <summary>
        /// 设置允许上传的扩展名
        /// </summary>
        public string[] AllowSuffix
        {
            get { return _allowSuffix; }
            set { _allowSuffix = value; }
        }

        /// <summary>
        /// 设置上传路径的根目录
        /// </summary>
        public string Root { get; set; }

        private string _pos = "";

        /// <summary>
        /// 设置上传根目录下的位置
        /// </summary>
        public string Pos
        {
            get
            {
                var path = Root + "sys\\";
                if (_pos.Trim() != "")
                {
                    path += _pos.Trim() + "\\";
                }
                return path;
            }
            set { _pos = value; }
        }

        /// <summary>
        /// 设置文件大小
        /// </summary>
        public int AllowFileSize { get; set; }

        /// <summary>
        /// 构造函数
        /// </summary>
        public FileUpload()
        {
            FileNames = new List<string[]>();
            AllowFileSize = 0;
        }

        /// <summary>
        /// 验证上传文件是否出错
        /// </summary>
        public bool HasError()
        {
            try
            {
                var ec = 0; 
                var files = Adp.Env.Current.Request.Form.Files;
                for (var i = 0; i < files.Count; i++)
                {
                    var f = files[i];
                    if (string.IsNullOrWhiteSpace(f.FileName))
                    {
                        ec++;
                        continue;
                    }
                    var suffix = Path.GetExtension(f.FileName).ToLower();
                    if (!AllowSuffix.Any(it => it.ToLower() == suffix))
                    {
                        ErrMsg = "上传的文件后缀不符合要求";
                        return true;
                    }
                    if (AllowFileSize > 0 && f.Length / 1024 / 1024 > AllowFileSize)
                    {
                        ErrMsg = "附件大小不能超过" + AllowFileSize + "M";
                        return true;
                    }
                }
                if (files.Count == ec)
                {
                    ErrMsg = "请选择文件";
                    return true;
                }
            }
            catch (Exception ex)
            {
                ErrMsg = ex.Message;
                return true;
            }
            return false;
        }

        /// <summary>
        /// 上传文件到指定目录下
        /// </summary>
        public bool Load()
        {
            if (HasError()) return false;
            try
            {
                var files = Adp.Env.Current.Request.Form.Files;
                for (var i = 0; i < files.Count; i++)
                {
                    var f = files[i];
                    var suffix = Path.GetExtension(f.FileName);
                    var tempPos = Pos;
                    var now = DateTime.Now;
                    if (!Directory.Exists(tempPos))
                        Directory.CreateDirectory(tempPos);
                    var rand = new Random();
                    var time = rand.Next(1000, 9999).ToString();
                    time += now.ToString("ddHHmmss");
                    time += rand.Next(0, 1000);
                    time += suffix;
                    using (var stream = new FileStream(tempPos + "\\" + time, FileMode.Create))
                    {
                        f.CopyTo(stream);
                    }
                    var srcname = "/sys/";
                    if (_pos.Trim() != "") srcname += _pos + "/";
                    FileNames.Add(new[] { srcname + time, time, f.FileName });
                }
                return true;
            }
            catch
            {
                return false;
            }
        }
    }
    #endregion

    #region 上传文件扩展名

    /// <summary>
    /// 上传文件扩展名
    /// </summary>
    public class FileSuffix
    {

        /// <summary>
        /// 模板扩展名
        /// </summary>
        public static string[] TemplateSuffix
        {
            get
            {
                return new[] { ".css", ".html", ".htm", ".js", ".ai", ".zip", ".rar", ".xml", ".mdb", ".aspx", ".asp", ".ascx", ".cshtml", ".cur", ".ico" };
            }
        }

        /// <summary>
        /// 文档扩展名
        /// </summary>
        public static string[] DocumentSuffix
        {
            get
            {
                return new[] { ".zip", ".rar", ".txt", ".rtf", ".jpg", ".jpeg", ".gif", ".bmp", ".png", ".tiff", ".svg", ".swf", ".wmv", ".avi", ".wma", ".mp3", ".aac", ".ogg", ".ac3", ".ra", ".mka", ".mp4", ".rm", ".rmvb", ".mkv", ".3gp", ".mov", ".mpg", ".mpeg", ".asf", ".mid", ".doc", ".docx", ".xls", ".xlsx", ".csv", ".pdf", ".flv", ".f4v", ".ppt", ".pptx" };
            }
        }

        /// <summary>
        /// 图片扩展名
        /// </summary>
        public static string[] ImageSuffix
        {
            get
            {
                return new[] { ".jpg", ".jpeg", ".gif", ".bmp", ".png", ".tiff", ".svg", ".ico" };
            }
        }

        /// <summary>
        /// 视频扩展名
        /// </summary>
        public static string[] VideoSuffix
        {
            get
            {
                return new[] { ".mp4", ".avi", ".wmv", ".mkv", ".rm", ".rmvb", ".flv", ".f4v", ".swf", ".asf", ".3gp", ".mov", ".mpg", ".mpeg", ".asf" };
            }
        }

        /// <summary>
        /// 音频扩展名
        /// </summary>
        public static string[] AudioSuffix
        {
            get
            {
                return new[] { ".mp3", ".aac", ".wma", ".ogg", ".ac3", ".ra", ".mka", ".mid" };
            }
        }

        /// <summary>
        /// Excel扩展名
        /// </summary>
        public static string[] ExcelSuffix
        {
            get
            {
                return new[] { ".xls", ".xlsx" };
            }
        }

        /// <summary>
        /// Word扩展名
        /// </summary>
        public static string[] WordSuffix
        {
            get
            {
                return new[] { ".doc", ".docx" };
            }
        }
    }

    #endregion

    #region 文件上传结果集

    /// <summary>
    /// 文件上传
    /// </summary>
    public class FileUploadResult : ActionResult
    {
        /// <summary>
        /// 上传根目录
        /// </summary>
        private readonly string _root;

        /// <summary>
        /// 上传根目录下的位置
        /// </summary>
        private readonly string _pos;

        /// <summary>
        /// 允许上传扩展名
        /// </summary>
        private readonly int _allowSuffix;

        /// <summary>
        /// 设置上传文件大小
        /// </summary>
        private readonly int _allowFileSize;


        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="root">上传根目录</param>
        /// <param name="pos">上传根目录下的位置</param>
        /// <param name="allowSuffix">允许上传扩展名</param>
        /// <param name="allowFileSize">设置上传文件大小</param>
        public FileUploadResult(string root, string pos = "", int allowSuffix = 0, int allowFileSize = 0)
        {
            _root = root;
            _pos = pos;
            _allowSuffix = allowSuffix;
            _allowFileSize = allowFileSize;
        }

        /// <summary>
        /// 执行结果
        /// </summary>
        /// <param name="context"></param>
        public override void ExecuteResult(ActionContext context)
        {
            var appendix = new FileUpload();
            appendix.Root = _root;
            appendix.Pos = _pos;
            appendix.AllowFileSize = _allowFileSize;
            switch (_allowSuffix)
            {
                case 1:
                    appendix.AllowSuffix = FileSuffix.ExcelSuffix;
                    break;
                case 2:
                    appendix.AllowSuffix = FileSuffix.ImageSuffix;
                    break;
                case 3:
                    appendix.AllowSuffix = FileSuffix.ImageSuffix.Concat(FileSuffix.VideoSuffix).ToArray();
                    break;
                default:
                    appendix.AllowSuffix = FileSuffix.DocumentSuffix;
                    break;
            }
            var response = context.HttpContext.Response;
            response.ContentType = "text/html";
            response.Headers.Add("Charset", "utf-8");
            string restr;
            if (appendix.HasError())
            {
                restr = JObject.FromObject(new
                {
                    success = false,
                    err = appendix.ErrMsg
                }).ToString();
            }
            else if (!appendix.Load())
            {
                restr = JObject.FromObject(new
                {
                    success = false,
                    err = "上传文件出错， 请与管理员联系。"
                }).ToString();
            }
            else
            {
                var fname = appendix.FileNames.First();
                restr = JObject.FromObject(new
                {
                    success = true,
                    srcname = fname[0],
                    filename = fname[1],
                    fname = fname[2]
                }).ToString();
            }
            var bt = Encoding.UTF8.GetBytes(restr);
            response.Body.Write(bt, 0, bt.Length);
        }
    }

    #endregion

    #region 文件下载结果集

    /// <summary>
    /// 文件下载
    /// </summary>
    public class FileDownloadResult : ActionResult
    {
        readonly string _absolutePath;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="absolutePath">文件绝对路径</param>
        public FileDownloadResult(string absolutePath)
        {
            _absolutePath = absolutePath;
        }

        /// <summary>
        /// 执行结果
        /// </summary>
        /// <param name="context"></param>
        public override void ExecuteResult(ActionContext context)
        {
            if (File.Exists(_absolutePath))
            {
                var filename = Path.GetFileName(_absolutePath);
                var response = context.HttpContext.Response;
                response.Headers.Add("Charset", "utf-8");
                response.Headers.Add("ContentEncoding", "utf-8");
                response.ContentType = "application/octet-stream";
                response.Headers.Add("Content-Disposition", "attachment; filename=" + WebUtility.UrlEncode(filename));
                response.Headers.Add("Cache-Control", "no-cache");
                using (FileStream fs = new FileStream(_absolutePath, FileMode.Open))
                {
                    var bytes = new byte[(int)fs.Length];
                    fs.Read(bytes, 0, bytes.Length);
                    fs.Close();
                    response.Body.Write(bytes, 0, bytes.Length);
                    response.Body.Flush();
                }
            }
        }
    }

    #endregion

}